package com.tanhua.server.service;

import com.alibaba.fastjson.JSON;
import com.tanhua.commons.template.AipFaceTemplate;
import com.tanhua.commons.template.HuanXinTemplate;
import com.tanhua.commons.template.OssTemplate;
import com.tanhua.commons.template.SmsTemplate;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.vo.ErrorResult;
import com.tanhua.dubbo.api.UserApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.util.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.Duration;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 这个类只用来处理controller的复杂业务逻辑,保证controller只与客户端交互
 *
 * @author anshuai
 * @create 2021-01-24 15:50
 */
@Slf4j
@Service
public class UserService {

    @Reference
    private UserApi userApi;
    @Reference
    private UserInfoApi userInfoApi;

    @Autowired
    private SmsTemplate smsTemplate;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private AipFaceTemplate aipFaceTemplate;
    @Autowired
    private OssTemplate ossTemplate;
    @Autowired
    private HuanXinTemplate huanXinTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Value("${tanhua.secret}")
    private String secret;

    /**
     * 发送短信验证码
     *
     * @param mobile 手机号码
     * @return 响应结果
     */
    public ResponseEntity sendSms(String mobile) {
        //1.发送手机验证码
        // String smsCode = smsTemplate.sendSms(mobile);
        String smsCode = "123456";

        //2. 把验证码存储到Redis里，设置有效期5分钟
        redisTemplate.opsForValue().set("CODE_" + mobile, smsCode, Duration.ofMinutes(5));

        //返回结果
        return ResponseEntity.ok(null);
    }

    /**
     * 登录注册
     *
     * @param mobile           手机号
     * @param verificationCode 验证码
     * @return 响应结果
     */
    public ResponseEntity loginVerification(String mobile, String verificationCode) {
        //1.校验验证码是否正常(将验证码信息从redis中取出来)
        String value = redisTemplate.opsForValue().get("CODE_" + mobile);
        //如果验证码为空或者验证码不正确
        if (value == null || !value.equals(verificationCode)) {
            //返回验证码失效
            return ResponseEntity.status(500).body(ErrorResult.smsInvalid());
        }
        //执行到这说明验证码正确,立即销毁验证码
        redisTemplate.delete("CODE_" + mobile);

        //2.根据手机号查询用户对象
        User user = userApi.findByMobile(mobile);
        //设置新用户标识
        boolean isNew = false;
        if (user == null) {
            //说明第一次登陆
            user = new User();
            user.setMobile(mobile);
            user.setPassword(DigestUtils.md5Hex("123456"));

            //保存到数据库
            /**
             * 因为添加用户服务是通过dubbo远程调用另一台服务器上的服务,那台服务器上是可以直接获取到用户的id,
             * 而我们的服务器上的用户拿不到id,所以只能接受添加用户方法的返回值来获取id,用作生成token作为用户的
             * 唯一标识
             */
            long userId = userApi.save(user);
            user.setId(userId);

            //把用户注册到环信
            huanXinTemplate.register(String.valueOf(userId), "123456");

            //标识新用户
            isNew = true;

        }

        //向RocketMQ里发送消息
        // 0101:登录，0102:注册
        Map<String, Object> message = new HashMap<>();
        message.put("userId", user.getId());
        message.put("type", isNew ? "0102" : "0101");
        message.put("date", new DateTime().toString("yyyy-MM-dd"));
        //发送消息
        rocketMQTemplate.convertAndSend("tanhua-log", message);

        log.info("发送操作日志信息, topic: {}, 消息内容: {}", "tanhua-log", message);

        //3.生成token
        String token = JwtUtils.createToken(mobile, user.getId(), secret);

        //4. 以token为key，把User数据存储到redis里
        //将user对象转换为json数据
        String userJson = JSON.toJSONString(user);
        //若长时间不操作,则销毁token数据
        redisTemplate.opsForValue().set("TOKEN_" + token, userJson, Duration.ofHours(1));

        //5.返回结果
        /**
         * 前端需要json数据如下:
         * "token": ""
         * "isNew": ""
         */
        //创建map存放数据
        HashMap<String, Object> result = new HashMap<>();
        result.put("token", token);
        //是否新用户
        result.put("isNew", isNew);

        //返回前端需要的数据
        return ResponseEntity.ok(result);
    }

    /**
     * 手机号登录-完善用户信息
     *
     * @param userInfo 用户信息
     * @return
     */
    public ResponseEntity saveUserInfo(UserInfo userInfo) {

        //根据token获取当前用户
        User user = UserHolder.getUser();
        Long userId = user.getId();

        //给userInfo补全数据
        userInfo.setId(userId);

        //保存用户信息
        userInfoApi.save(userInfo);

        //返回结果
        return ResponseEntity.ok(null);
    }


    /**
     * 登录注册-完善个人资料-上传头像
     *
     * @param headPhoto 用户头像
     * @return
     */
    public ResponseEntity saveAvatar(MultipartFile headPhoto) throws IOException {

        //从redis中获取当前用户
        User user = UserHolder.getUser();

        //对用户上传的头像进行人脸识别
        boolean detect = aipFaceTemplate.detect(headPhoto.getBytes());
        //如果不是人脸,直接返回响应
        if (!detect) {
            return ResponseEntity.status(500).body(ErrorResult.faceDetectFailed());
        }

        //将头像上传到阿里云
        String path = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());

        //更新数据库
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId());
        userInfo.setAvatar(path);
        userInfoApi.update(userInfo);

        return ResponseEntity.ok(null);
    }
}
